package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.sc.nft.dao.*;
import com.sc.nft.dto.CollectionChipCreateDTO;
import com.sc.nft.dto.CollectionChipReceiveDTO;
import com.sc.nft.dto.CollectionChipUserGetDTO;
import com.sc.nft.entity.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.*;
import com.sc.nft.exception.GlobalRunTimeException;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.dao.CollectionChipDao;
import com.sc.nft.dao.CollectionChipInfoDao;
import com.sc.nft.dao.DigitalCollectionProductInfoDao;
import com.sc.nft.dao.ProductStockDao;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.CollectionChipDTO;
import com.sc.nft.enums.CommodityType;
import com.sc.nft.enums.wallet.MallDaoWalletTypeEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.CollectionChipService;
import com.sc.nft.service.ProductStockService;
import com.sc.nft.service.UserCollectionService;
import com.sc.nft.sup.ErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;

import java.util.Date;
import java.util.List;

@Slf4j
@RequiredArgsConstructor
@Service
public class CollectionChipServiceImpl implements CollectionChipService {

    private final CollectionChipDao collectionChipDao;
    private final DigitalCollectionProductInfoDao digitalCollectionProductInfoDao;
    private final ProductStockDao productStockDao;
    private final ProductStockService productStockService;
    private final CollectionChipInfoDao collectionChipInfoDao;
    private final CollectionChipInfoRecordDao collectionChipInfoRecordDao;
//    private final UserCollectionDao userCollectionDao;
    private final DigitalCollectionDao digitalCollectionDao;
    private final CollectionChipReceiveRecordDao collectionChipReceiveRecordDao;
    private final UserCollectionService userCollectionService;

    /**
     * 创建芯片程序
     *
     * @param collectionChipDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(CollectionChipCreateDTO collectionChipDTO) {
        if (collectionChipDTO.getReceiveLimit() == 1 && collectionChipDTO.getLimitProductId() == null) {
            throw new GlobalRunTimeException("请关联领取限制商品");
        }
        //判断此商品是否被绑定过
        Integer checkResult = collectionChipDao.checkProductBind(collectionChipDTO.getProductId());
        if (checkResult == null || checkResult > 0) {
            throw new GlobalRunTimeException("此商品已被绑定");
        }
        CollectionChip collectionChip = new CollectionChip();
        BeanUtil.copyProperties(collectionChipDTO,collectionChip);
        collectionChipDao.save(collectionChip);
        //查询关联商品
        DigitalCollectionProductInfo digitalCollectionProductInfo = digitalCollectionProductInfoDao.getById(collectionChipDTO.getProductId());
        if (Objects.isNull(digitalCollectionProductInfo)) {
            throw new GlobalRunTimeException("商品不存在");
        }
        if (CommodityType.CHIP != digitalCollectionProductInfo.getCommodityType()) {
            throw new GlobalRunTimeException("商品类型错误");
        }
        //根据库存生成collectionChipInfo信息
        ProductStock byProductId = productStockDao.getByProductId(collectionChipDTO.getProductId());
        Integer usableCount = byProductId.getUsableCount();
        //生成collectionChipInfo
        List<CollectionChipInfo> collectionChipInfoList = new ArrayList<>();
        for (Integer i = 1; i <= usableCount; i++) {
            CollectionChipInfo collectionChipInfo = new CollectionChipInfo();
            collectionChipInfo.setCollectionChipId(collectionChip.getId());
            collectionChipInfo.setUuid(IdUtil.simpleUUID());
            collectionChipInfo.setReceiveStatus(0);
            collectionChipInfo.setWriteStatus(0);
            collectionChipInfoList.add(collectionChipInfo);
        }
        collectionChipInfoDao.saveList(collectionChipInfoList);
    }


    /**
     * 用户端NFC扫描出来后的信息
     *
     * @return
     */
    @Override
    public CollectionChipUserDetailsVO userGetCollectionChip(CollectionChipUserGetDTO dto,UserInfo userInfo) {
        CollectionChipInfo collectionChipInfo = null;
        // 解码
        String[] split = null;
        String uuid = null;
        try {
            byte[] decodedBytes = Base64.getDecoder().decode(dto.getCode());
            String decodedString = new String(decodedBytes);
            split = decodedString.split(":");
            uuid = split[1];
        } catch (Exception e) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_NOT_FOUND);
        }
        try {
            collectionChipInfo = collectionChipInfoDao.getById(Long.valueOf(split[0]));
        } catch (NumberFormatException e) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_NOT_FOUND);
        }
        if (Objects.isNull(collectionChipInfo)) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_NOT_FOUND);
        }
        if (!collectionChipInfo.getUuid().equals(uuid)) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_NOT_FOUND);
        }
        CollectionChipUserDetailsVO collectionChipUserDetailsVO = new CollectionChipUserDetailsVO();
        CollectionChip collectionChip = collectionChipDao.getById(collectionChipInfo.getCollectionChipId());
        if (Objects.isNull(collectionChip)) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_EXPIRE);
        }
        //扫描记录
        CollectionChipInfoRecord infoRecord = new CollectionChipInfoRecord();
        infoRecord.setUserId(userInfo.getId());
        infoRecord.setCollectionChipInfoId(collectionChipInfo.getId());
        infoRecord.setReceiveStatus(0);
        infoRecord.setRecognitionTime(new Date());
        collectionChipInfoRecordDao.save(infoRecord);
        Integer count = collectionChipInfoRecordDao.countByCollectionInfo(collectionChipInfo.getId());
        collectionChipUserDetailsVO.setRecognitionNum(count);
        collectionChipUserDetailsVO.setDetailsImage(collectionChip.getDetailsImage());
        collectionChipUserDetailsVO.setCoverImage(collectionChip.getCoverImage());
        collectionChipUserDetailsVO.setCanReceive(collectionChipInfo.getReceiveStatus() == 0);
        if (collectionChipInfo.getReceiveStatus() == 1) {
            UserCollection userCollection = userCollectionService.getById(collectionChipInfo.getUserCollectionId());
            if (Optional.ofNullable(userCollection).isPresent()) {
                CollectionChainDetailDTO collectionChainDetail = userCollectionService.getCollectionChainDetail(userCollection);
                collectionChipUserDetailsVO.setTianheChain(collectionChainDetail.getTianheChain());
                collectionChipUserDetailsVO.setChainUrl(collectionChainDetail.getChainUrl());
                DigitalCollection digitalCollection = digitalCollectionDao.getById(userCollection.getCollectionId());
                if (Optional.ofNullable(digitalCollection).isPresent()) {
                    collectionChipUserDetailsVO.setDeployTransactionHash(digitalCollection.getDeployTransactionHash());
                }
            }
        }
        return collectionChipUserDetailsVO;
    }


    /**
     * 用户领取
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void userGetCollectionChipReceive(CollectionChipUserGetDTO dto,UserInfo userInfo) {
        Long userId = userInfo.getId();
        // 解码
        String[] split = null;
        String uuid = null;
        try {
            byte[] decodedBytes = Base64.getDecoder().decode(dto.getCode());
            String decodedString = new String(decodedBytes);
            split = decodedString.split(":");
            uuid = split[1];
        } catch (Exception e) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_NOT_FOUND);
        }
        CollectionChipInfo collectionChipInfo = collectionChipInfoDao.getById(Long.valueOf(split[0]));
        if (Objects.isNull(collectionChipInfo)) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_NOT_FOUND);
        }
        if (!collectionChipInfo.getUuid().equals(uuid)) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_NOT_FOUND);
        }
        if (collectionChipInfo.getReceiveStatus() == 1) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_HAS_BEEN_PICKED_UP);
        }
        CollectionChip collectionChip = collectionChipDao.getById(collectionChipInfo.getCollectionChipId());
        if (Objects.isNull(collectionChip)) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_EXPIRE);
        }
        //判断用户限制领取
        if (collectionChip.getReceiveLimit() == 1) {
            if (null != collectionChip.getLimitProductId() && collectionChip.getLimitProductId() != 0) {
                List<UserCollection> list = userCollectionService.getListByCollercitonId(userId, collectionChip.getLimitProductId());
                if(list.size() <=0){
                    throw new GlobalRunTimeException(ErrorCode.CHIP_LIMIT);
                }
            }else {
                throw new GlobalRunTimeException(ErrorCode.CHIP_RECEIVE_FAIL);
            }
        }
        //查询商品
        DigitalCollectionProductInfo product = digitalCollectionProductInfoDao.getById(collectionChip.getProductId());
        if (Objects.isNull(product)) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_EXPIRE);
        }
        Integer usableStockCount = productStockDao.getUsableStockCount(collectionChip.getProductId());
        if (usableStockCount <= 0) {
            throw new GlobalRunTimeException(ErrorCode.INSUFFICIENT_STOCK);
        }
        DigitalCollection collection = digitalCollectionDao.getById(product.getRelationId());
        Boolean reduceResult = productStockDao.deductStock(product.getId(), product.getRelationId(), 1);
        Assert.isTrue(reduceResult, () -> new GlobalRunTimeException("库存不足"));
        ProductStockDetail stockDetail = new ProductStockDetail();
        stockDetail.setProductId(product.getId());
        stockDetail.setRelationId(product.getRelationId());
        stockDetail.setStockChange(0 - 1);
        stockDetail.setUserId(userId);
        stockDetail.setType(CommodityType.CHIP);
        stockDetail.insert();
        //给用户添加藏品
        UserCollection userCollection = userCollectionService.addCollection(userId, null, collection.getId(), IdUtil.getSnowflakeNextIdStr(), product.getCreationContent(), collection.getLevel(), collection.getFirstTitle(), product.getUserCreatorId(), ReceivedCollectionType.CHIP, null, null, null, Boolean.TRUE, product.getId(), 0L, 0L, BigDecimal.ZERO, 0, null, null, AddCollectionEnum.DEFAULT,null,null,false);
        //添加藏品流转记录
        CollectionCirculatingRecord collectionCirculatingRecord = new CollectionCirculatingRecord();
        collectionCirculatingRecord.setUserId(userId);
        collectionCirculatingRecord.setCollectionId(collection.getId());
        collectionCirculatingRecord.setCommodityType(CommodityType.CHIP);
        collectionCirculatingRecord.setTypeClassify(ClassifyType.COLLECTION);
        collectionCirculatingRecord.setReceivedCollectionType(ReceivedCollectionType.CHIP);
        collectionCirculatingRecord.setToUserCollection(userCollection.getId());
        collectionCirculatingRecord.setToUserId(userCollection.getId());
        collectionCirculatingRecord.setOrderId(0L);
        collectionCirculatingRecord.setInviteTaskId(0L);
        collectionCirculatingRecord.setUserReceiveInviteId(0L);
        collectionCirculatingRecord.setUserReceiveIntegraId(0L);
        collectionCirculatingRecord.setAirdropGrantRecordId(0L);
        collectionCirculatingRecord.setUserSynthesisRecordId(0L);
        collectionCirculatingRecord.setNumber(userCollection.getNumbering());
        collectionCirculatingRecord.insert();
        //生成领取记录
        CollectionChipReceiveRecord collectionChipReceiveRecord = new CollectionChipReceiveRecord();
        collectionChipReceiveRecord.setCollectionChipId(collectionChip.getId());
        collectionChipReceiveRecord.setCollectionChipInfoId(collectionChipInfo.getId());
        collectionChipReceiveRecord.setUserId(userId);
        collectionChipReceiveRecord.setReceiveTime(new Date());
        collectionChipReceiveRecordDao.save(collectionChipReceiveRecord);
        //查询用户最新一条识别记录
        CollectionChipInfoRecord collectionChipInfoRecord = collectionChipInfoRecordDao.getNewOneByUserIdAndChipInfoId(userId,collectionChipInfo.getId());
        if (Objects.isNull(collectionChipInfoRecord)) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_RECEIVE_FAIL);
        }
        Assert.isTrue(collectionChipInfoRecordDao.updateReceiveStatusById(collectionChipInfoRecord.getId(),1),()->new GlobalRunTimeException(ErrorCode.CHIP_RECEIVE_FAIL));
        //修改状态
        Assert.isTrue(collectionChipInfoDao.updateReceiveStatusAndUserCollectionId(collectionChipInfo.getId(), 1,userCollection.getId()), () -> new GlobalRunTimeException(ErrorCode.CHIP_RECEIVE_FAIL));

    }

    /**
     * 识别记录
     *
     * @param dto
     * @param user
     * @return
     */
    @Override
    public void userGetCollectionChipRecord(CollectionChipUserGetDTO dto, UserInfo userInfo) {
        CollectionChipInfo collectionChipInfo = null;
        // 解码
        String[] split = null;
        String uuid = null;
        try {
            byte[] decodedBytes = Base64.getDecoder().decode(dto.getCode());
            String decodedString = new String(decodedBytes);
            split = decodedString.split(":");
            uuid = split[1];
        } catch (Exception e) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_NOT_FOUND);
        }
        try {
            collectionChipInfo = collectionChipInfoDao.getById(Long.valueOf(split[0]));
        } catch (NumberFormatException e) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_NOT_FOUND);
        }
        if (Objects.isNull(collectionChipInfo)) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_NOT_FOUND);
        }
        if (!collectionChipInfo.getUuid().equals(uuid)) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_NOT_FOUND);
        }
        CollectionChip collectionChip = collectionChipDao.getById(collectionChipInfo.getCollectionChipId());
        if (Objects.isNull(collectionChip)) {
            throw new GlobalRunTimeException(ErrorCode.CHIP_EXPIRE);
        }
        CollectionChipInfoRecord infoRecord = new CollectionChipInfoRecord();
        infoRecord.setUserId(userInfo.getId());
        infoRecord.setCollectionChipInfoId(collectionChipInfo.getId());
        infoRecord.setReceiveStatus(0);
        infoRecord.setRecognitionTime(new Date());
        collectionChipInfoRecordDao.save(infoRecord);
    }

    /**
     * 领取记录
     *
     * @param receiveDTO
     * @return
     */
    @Override
    public IPage<CollectionChipReceivePageVO> receiveRecord(CollectionChipReceiveDTO receiveDTO) {
        return collectionChipReceiveRecordDao.receiveRecord(receiveDTO);
    }


    /**
     * 后台芯片程序列表
     * @param collectionChipDTO
     * @return
     */
    @Override
    public Page<CollectionChipVO> getAdminCollectionChipPage(CollectionChipDTO collectionChipDTO) {

        Page<CollectionChipVO> collectionChipPage = collectionChipDao.getCollectionChipPage(collectionChipDTO);
        List<CollectionChipVO> collectionChipPageRecords = collectionChipPage.getRecords();
        for (CollectionChipVO collectionChipVO : collectionChipPageRecords) {
            ProductStockChipCountVO productStockChipCountVO = productStockDao.getChipCount(collectionChipVO.getProductId());
            if (Objects.nonNull(productStockChipCountVO)){
                collectionChipVO.setProductCount(productStockChipCountVO.getProductCount());
                collectionChipVO.setProductName(productStockChipCountVO.getProductName());
            }
            List<CollectionChipInfo> infoList = collectionChipInfoDao.getByChipId(collectionChipVO.getId());
            if (!CollectionUtils.isEmpty(infoList)){
                collectionChipVO.setWriteCount(Convert.toInt(infoList.stream().filter(e -> e.getWriteStatus() == 1).count()));
                collectionChipVO.setNotReceivedCount(Convert.toInt(infoList.stream().filter(e -> e.getReceiveStatus() == 0).count()));
                collectionChipVO.setReceivedAlreadyCount(infoList.size() - collectionChipVO.getNotReceivedCount());
            }
        }
        return collectionChipPage;

    }


    /**
     * 芯片 详情
     * @param id
     * @return
     */
    @Override
    public CollectionChipDetailsVO getCollectionChipDetails(Long id){
        CollectionChip collectionChip = collectionChipDao.getCollectionChipById(id);
        Assert.notNull(collectionChip, () -> new GlobalRunTimeException("芯片不存在"));
        CollectionChipDetailsVO collectionChipDetailsVO = BeanUtil.copyProperties(collectionChip, CollectionChipDetailsVO.class);
        DigitalCollectionProductInfo productByCommodityType = digitalCollectionProductInfoDao.getProductByCommodityType(collectionChip.getProductId(), CommodityType.CHIP);
        if (Objects.isNull(productByCommodityType)){
            throw new GlobalRunTimeException("数据异常");
        }
        collectionChipDetailsVO.setProductName(productByCommodityType.getFirstTitle());
        if (Objects.nonNull(collectionChip.getLimitProductId())){
            DigitalCollection digitalCollection = digitalCollectionDao.getById(collectionChip.getLimitProductId());
            collectionChipDetailsVO.setCollectionName(digitalCollection.getFirstTitle());
        }
        return collectionChipDetailsVO;
    }


}
